package com.view;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.View;

import com.usercarshow.MainActivity;
import com.usercarshow.R;

public class MainView extends View {
	// stone列表
	private BigStone[] mStones;
	// 数目
	private static final int STONE_COUNT = 5;
	// 图标之间夹角度数
	private static final int SEP_ANGLE = 30;
	// 初始化图标角度
	private static int[] initAngle = { 240, 210, 180, 150, 120 };
	// 圆心坐标及半径
	private int mPointX = 0, mPointY = 0, mRadius = 0;

	// 当前选中按钮
	private Bitmap currentAction;
	// 当前标题水平位置
	private final static int CUR_BITMAP_X = 25;
	// 当前标题垂直位置
	private final static int CUR_BITMAP_Y = 20;
	// 上方边界角度
	private final static int SIDE_TOP_ANGLE = 270;
	// 下方边界角度
	private final static int SIDE_BOTTOM_ANGLE = 90;
	// 边界调整角度
	private final static int SIDE_ADJUST_ANGLE = 210;
	// 当前圆周角度
	private final static int CIRCLE_ANGLE = 360;

	// 记录上一次单击位置
	private int lastClickedPos = 0;

	// 转动事件信息
	private EventInfo eventInfo = new EventInfo();
	// 转动动画信息
	private AnimationInfo animationInfo = new AnimationInfo();

	public MainView(Context context, int px, int py, int radius) {
		super(context);
		setFocusableInTouchMode(true);
		setBackgroundResource(R.drawable.mainbg);
		mPointX = px;
		mPointY = py;
		mRadius = radius;

		setupStones();
		computeCoordinates();
	}

	/**
	 * 初始化每个点
	 */
	private void setupStones() {
		mStones = new BigStone[STONE_COUNT];
		BigStone stone;

		for (int i = 0; i < STONE_COUNT; i++) {
			stone = new BigStone();
			stone.angle = initAngle[i];
			stone.cacheAngle = initAngle[i];
			// 初始化按钮背景
			stone.bitmap = BitmapFactory.decodeResource(getResources(),
					R.drawable.nav_1 + i);
			// 初始化按钮单击背景
			stone.ClickedBitmap = BitmapFactory.decodeResource(getResources(),
					R.drawable.clicked_nav1 + i);
			// 初始化标题背景
			stone.titleBitmap = BitmapFactory.decodeResource(getResources(),
					R.drawable.describe_1 + i);
			mStones[i] = stone;
		}
		// 设置默认选中状态
		mStones[0].setClicked(true);
		// 默认加载第一项
		currentAction = BitmapFactory.decodeResource(getResources(),
				R.drawable.describe_1);
	}

	/**
	 * 根据度数计算每个点的坐标 （x1=x0+r*cosθ，y1=y0+r*sinθ）
	 */
	private void computeCoordinates() {
		if (eventInfo.getTouchStatus() == EventInfo.ACTION_MOVE) { // 移动状态
			for (int i = 0; i < STONE_COUNT; i++) {
				mStones[i].x = mPointX + mRadius
						* CommonTools.getCosValueByAngle(mStones[i].cacheAngle);
				mStones[i].y = mPointY + mRadius
						* CommonTools.getSinValueByAngle(mStones[i].cacheAngle);
			}
		} else if (eventInfo.getTouchStatus() == EventInfo.ACTION_UP) { // 即时松开状态
			for (int i = 0; i < STONE_COUNT; i++) {
				mStones[i].x = mPointX + mRadius
						* CommonTools.getCosValueByAngle(mStones[i].cacheAngle);
				mStones[i].y = mPointY + mRadius
						* CommonTools.getSinValueByAngle(mStones[i].cacheAngle);
			}
		} else if (eventInfo.getTouchStatus() == EventInfo.ACTION_NO) { // 默认状态
			for (int i = 0; i < STONE_COUNT; i++) {
				mStones[i].x = mPointX + mRadius
						* CommonTools.getCosValueByAngle(mStones[i].angle);
				mStones[i].y = mPointY + mRadius
						* CommonTools.getSinValueByAngle(mStones[i].angle);
			}
		}
	}

	/**
	 * 重新计算每个点的角度
	 */
	private void resetStonesAngle() {
		if (eventInfo.isOverHalf()) {
			int touchAngle = eventInfo.reCountTouchAngle(mPointX, mPointY,
					mRadius);// 重新计算滑动的角度

			if (eventInfo.getTouchStatus() == EventInfo.ACTION_MOVE) { // 移动状态,调整跟随速度
				for (int i = 0; i < STONE_COUNT; i++) {
					if (eventInfo.detectDirec() == EventInfo.TOUCH_UP) {// 向上移动
						mStones[i].cacheAngle = mStones[i].angle + touchAngle;
					} else if (eventInfo.detectDirec() == EventInfo.TOUCH_DOWN) { // 向下移动
						mStones[i].cacheAngle = mStones[i].angle - touchAngle;
					}
					if (mStones[i].cacheAngle > MainView.SIDE_TOP_ANGLE) {
						mStones[i].cacheAngle = (mStones[i].cacheAngle + MainView.SIDE_ADJUST_ANGLE)
								% MainView.CIRCLE_ANGLE;
					} else if (mStones[i].cacheAngle < MainView.SIDE_BOTTOM_ANGLE) {
						mStones[i].cacheAngle = (mStones[i].cacheAngle
								- MainView.SIDE_ADJUST_ANGLE + MainView.CIRCLE_ANGLE)
								% MainView.CIRCLE_ANGLE;
					}
				}
			} else if (eventInfo.getTouchStatus() == EventInfo.ACTION_UP) { // 松开状态，计算加速或加速调整速度
				if (animationInfo.isStarted) { // 动画是否启动
					animationInfo.setStep(touchAngle / MainView.SEP_ANGLE);
					int extra = touchAngle % MainView.SEP_ANGLE;

					if (extra < MainView.SEP_ANGLE / 2) {
						animationInfo.setAnimalDir(AnimationInfo.ANIMAL_DOWN);// 设置动画方向
						animationInfo.setChangeAngle(extra);// 设置动画转动角度
					} else {
						animationInfo.setStep(animationInfo.getStep() + 1);
						animationInfo.setAnimalDir(animationInfo.ANIMAL_UP);// 设置动画方向
						animationInfo
								.setChangeAngle(MainView.SEP_ANGLE - extra);// 设置动画转动角度
					}
					if (animationInfo.getStep() > 0) {
						changeAngle(animationInfo.getStep()); // 调整角度
					}
					if (animationInfo.getChangeAngle() > 0) { // 角度是否需要调整
						animationInfo.setInitRate(animationInfo
								.countInitRate(animationInfo.getChangeAngle())); // 计算初始角速度
					}
					animationInfo.isStarted = false;// 关闭动画
				}
				if (animationInfo.getChangeAngle() > 0) { // 存在调整角度
					for (int i = 0; i < STONE_COUNT; i++) {
						// 匀速滑动距离
						int distanse = animationInfo.countConstantDistance(1);
						if (distanse > 0) { // 检测距离是否存在
							if (animationInfo.getAnimalDir() == AnimationInfo.ANIMAL_UP) {
								mStones[i].cacheAngle += distanse;
							} else if (animationInfo.getAnimalDir() == AnimationInfo.ANIMAL_DOWN) {
								mStones[i].cacheAngle -= distanse;
							}
						}
						// 设置滑动之后角度
						animationInfo.setChangeAngle(animationInfo
								.getChangeAngle() - distanse);
						// changeAngle--;
						if (mStones[i].cacheAngle > MainView.SIDE_TOP_ANGLE) {
							mStones[i].cacheAngle = (mStones[i].cacheAngle + MainView.SIDE_ADJUST_ANGLE)
									% MainView.CIRCLE_ANGLE;
						} else if (mStones[i].cacheAngle < MainView.SIDE_BOTTOM_ANGLE) {
							mStones[i].cacheAngle = (mStones[i].cacheAngle
									- MainView.SIDE_ADJUST_ANGLE + MainView.CIRCLE_ANGLE)
									% MainView.CIRCLE_ANGLE;
						}
					}

				} else { // 不存在调整状态，恢复默认状态
					eventInfo.resetTouchStatus();
					eventInfo.resetTouchAngle();// 恢复转动角度
				}
			}
		}
	}

	/** 调整页面元素坐标 */
	private void changeAngle(int step) {
		int[] array = new int[STONE_COUNT];
		int len = step % STONE_COUNT;
		int j = 0;
		if (eventInfo.detectDirec() == EventInfo.TOUCH_UP) { // 向上移动调整
			for (int i = STONE_COUNT - len; i < STONE_COUNT; i++) {
				array[j++] = mStones[i].angle;
			}
			for (int i = 0; i < STONE_COUNT - len; i++) {
				array[j++] = mStones[i].angle;
			}
			for (int i = 0; i < STONE_COUNT; i++) {
				mStones[i].angle = array[i];
			}
		} else if (eventInfo.detectDirec() == EventInfo.TOUCH_DOWN) { // 向下移动调整
			for (int i = len; i < STONE_COUNT; i++) {
				array[j++] = mStones[i].angle;
			}
			for (int i = 0; i < len; i++) {
				array[j++] = mStones[i].angle;
			}
			for (int i = 0; i < STONE_COUNT; i++) {
				mStones[i].angle = array[i];
			}
		}
	}

	/**
	 * 把中心点放到中心处
	 * 
	 * @param canvas
	 * @param bitmap
	 * @param left
	 * @param top
	 */
	private void drawInCenter(Canvas canvas, Bitmap bitmap, double left,
			double top) {
		// 某张图片的中心坐标
		canvas.drawBitmap(bitmap, (float) left - bitmap.getWidth() / 2,
				(float) top - bitmap.getHeight() / 2, null);
	}

	@Override
	public void onDraw(Canvas canvas) {
		for (int i = 0; i < STONE_COUNT; i++) {
			if (!mStones[i].isVisible())
				continue;
			if (mStones[i].isClicked()) { // “单击” 事件发生
				// 绘制 “单击背景”
				drawInCenter(canvas, mStones[i].ClickedBitmap, mStones[i].x,
						mStones[i].y);
				// 绘制 ”标题“
				canvas.drawBitmap(mStones[i].titleBitmap,
						MainView.CUR_BITMAP_X, MainView.CUR_BITMAP_Y, null);
			} else {
				drawInCenter(canvas, mStones[i].bitmap, mStones[i].x,
						mStones[i].y);
			}
		}

		resetStonesAngle();
		computeCoordinates();
		invalidate();
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent e) {
		if (e.getAction() == MotionEvent.ACTION_DOWN) { // 按下,检测是否作用到合适的范围内
			eventInfo.setTouchStatus(EventInfo.ACTION_DOWN);
			eventInfo.setStartPx(e.getX());
			eventInfo.setStartPy(e.getY());
			checkClickRange();// 检测单击范围
		} else if (e.getAction() == MotionEvent.ACTION_MOVE) { // 移动
			eventInfo.setTouchStatus(EventInfo.ACTION_MOVE);
			eventInfo.reCountTouchAngle(mPointX, mPointY, mRadius);// 重新计算触摸角度
			eventInfo.setEndPx(e.getX());
			eventInfo.setEndPy(e.getY());
		} else if (e.getAction() == MotionEvent.ACTION_UP) {// 松开
			eventInfo.setTouchStatus(EventInfo.ACTION_UP);
			animationInfo.setStarted(true);// 开启动画
			eventInfo.reCountTouchAngle(mPointX, mPointY, mRadius);// 重新计算触摸角度
			eventInfo.setEndPx(e.getX());
			eventInfo.setEndPy(e.getY());
			// resetClickRange();// 恢复单击范围内状态
		}
		return super.dispatchTouchEvent(e);
	}

	@Override
	public boolean onTouchEvent(MotionEvent e) {
		if (e.getAction() == MotionEvent.ACTION_DOWN) {
			eventInfo.selfAddClickNum();
			if (eventInfo.getClickNum() == 1) {
				eventInfo.setFirstClickTime(System.currentTimeMillis());
				eventInfo.setFirstClickPx(e.getX());
				eventInfo.setFirstClickPy(e.getY());
			} else if (eventInfo.getClickNum() == 2) {
				eventInfo.setSecondClickTime(System.currentTimeMillis());
				if (eventInfo.getSecondClickTime()
						- eventInfo.getFirstClickTime() < EventInfo.CLICK_DELAY_TIME
						&& (eventInfo.getFirstClickPx() == e.getX() && eventInfo
								.getFirstClickPy() == e.getY())) {
					// 双击事件
					if (mStones[0].isClicked()) {
						Intent intent = new Intent(MainActivity.main,
								ExhibitHot.class);
						intent.putExtra("clickedName", "选取名称");
						MainActivity.main.startActivity(intent);
						MainActivity.main
								.overridePendingTransition(
										android.R.anim.fade_in,
										android.R.anim.fade_out);
					} else if (mStones[2].isClicked()) {
						Intent intent = new Intent(MainActivity.main,
								ExhibitPrice.class);
						intent.putExtra("clickedName", "选取名称");
						MainActivity.main.startActivity(intent);
						MainActivity.main
								.overridePendingTransition(
										android.R.anim.fade_in,
										android.R.anim.fade_out);
					} else if (mStones[3].isClicked) {
						Intent intent = new Intent(MainActivity.main,
								ExhibitBrand.class);
						intent.putExtra("clickName", "选取名称");
						MainActivity.main.startActivity(intent);
						MainActivity.main
								.overridePendingTransition(
										android.R.anim.fade_in,
										android.R.anim.fade_out);
					} else if (mStones[4].isClicked()) {
						Intent intent = new Intent(MainActivity.main,
								ExhibitType.class);
						intent.putExtra("clickedName", "选取名称");
						MainActivity.main.startActivity(intent);
						MainActivity.main
								.overridePendingTransition(
										android.R.anim.fade_in,
										android.R.anim.fade_out);
					}
				}
				// 恢复初始事件
				eventInfo.resetClickInfo();
			}
		}
		return true;
	}

	/**
	 * 检测单击范围
	 */
	private void checkClickRange() {
		int i = 0;
		for (; i < STONE_COUNT; i++) {
			// 记录上一个状态选中
			if (mStones[i].isClicked()) {
				lastClickedPos = i;
			}
		}
		// 恢复单击状态
		resetClickRange();
		for (i = 0; i < STONE_COUNT; i++) {
			boolean isClicked = mStones[i].checkClickRange(
					eventInfo.getStartPx(), eventInfo.getStartPy());
			if (isClicked) {
				break;
			}
		}
		if (i >= STONE_COUNT) {// 没有任何被选中,设置默认值
			mStones[lastClickedPos].setClicked(true);
		}
	}

	/**
	 * 恢复单击范围内状态
	 */
	private void resetClickRange() {
		for (int i = 0; i < STONE_COUNT; i++) {
			if (mStones[i].isClicked) {
				mStones[i].setClicked(false);
			}
		}
	}

	private final class AnimationInfo {
		private static final int ANIMAL_UP = 1;// 沿触摸点向上
		private static final int ANIMAL_DOWN = 2;// 沿触摸点向下
		private int animalDir = 0;// 动画方向
		private int step = 0; // 动画调整长度

		// 动画的初始加速度
		private int accent = 1;
		// 动画的初始速度
		private int initRate = 0;
		// 微调角度
		private int changeAngle = 0;
		// 动画是否已经开启
		private boolean isStarted = false;

		/** 计算初始角速度 */
		public int countInitRate(int angle) {
			return (int) Math.sqrt(2 * accent * angle);
		}

		/** 根据加速度调整速度 */
		private int countPerRateByAccent(int currentA) {
			int perTime = 1;
			return currentA - accent * perTime;
		}

		/** 计算加速距离 */
		public int countAccentDistance() {
			return (int) (getChangeAngle() - countPerRateByAccent(getChangeAngle())) / 2;
		}

		/** 计算匀速距离 */
		public int countConstantDistance(int distance) {
			return distance;
		}

		public int getAnimalDir() {
			return animalDir;
		}

		public void setAnimalDir(int animalDir) {
			this.animalDir = animalDir;
		}

		public int getAccent() {
			return accent;
		}

		public void setAccent(int accent) {
			this.accent = accent;
		}

		public int getInitRate() {
			return initRate;
		}

		public void setInitRate(int initRate) {
			this.initRate = initRate;
		}

		public int getChangeAngle() {
			return changeAngle;
		}

		public void setChangeAngle(int changeAngle) {
			this.changeAngle = changeAngle;
		}

		public boolean isStarted() {
			return isStarted;
		}

		public void setStarted(boolean isStarted) {
			this.isStarted = isStarted;
		}

		public int getStep() {
			return step;
		}

		public void setStep(int step) {
			this.step = step;
		}

	}

	/** 每个图片的具体位置 */
	private final class BigStone {
		// “未单击” 图片
		private Bitmap bitmap;
		// “单击” 图片
		private Bitmap ClickedBitmap;
		// "标题"图片
		private Bitmap titleBitmap;
		// 角度
		private int angle;
		// 滑动缓存角度
		private int cacheAngle;
		// x坐标
		private double x;
		// y坐标
		private double y;
		// 是否可见
		private boolean isVisible = true;
		// 是否处于 “点击”状态
		private boolean isClicked = false;
		// 边界触发范围
		private static final int range = 25;

		// 判断是否处于 “点击范围”
		public boolean checkClickRange(double startPx, double startPy) {
			if (startPx >= (this.x - range)
					&& startPx <= (this.x + this.bitmap.getWidth() + range)
					&& startPy >= (this.y - range)
					&& startPy <= (this.y + this.bitmap.getHeight() + range)) {
				return isClicked = true;
			}
			return false;
		}

		public boolean isVisible() {
			return isVisible;
		}

		public void setVisible(boolean isVisible) {
			this.isVisible = isVisible;
		}

		public boolean isClicked() {
			return isClicked;
		}

		public void setClicked(boolean isClicked) {
			this.isClicked = isClicked;
		}
	}

	/** 事件信息类 */
	private final class EventInfo {
		private static final int TOUCH_UP = 1;// 沿触摸点向上
		private static final int TOUCH_DOWN = 2;// 沿触摸点向下
		private int direc = 0;// 当前默认方向--无方向

		// 当前状态
		static final int ACTION_DOWN = 0;
		static final int ACTION_UP = 1;
		static final int ACTION_MOVE = 2;
		static final int ACTION_NO = 0;
		// 触摸状态--无状态
		private int touchStatus = ACTION_NO;

		protected static final int CLICK_DELAY_TIME = 500;// 区别单双击时间间隔

		private double startPx; // 点击起始点
		private double startPy; // 点击起始点
		private double endPx; // 点击结束点
		private double endPy;// 点击结束点
		private int clickNum = 0; // 单击次数，用于判断是否为双击
		private Long firstClickTime;// 第一次单击时间
		private double firstClickPx; // 第一次单击水平位置
		private double firstClickPy;// 第一次单击垂直位置
		private Long secondClickTime;// 第二次单击时间
		private int touchAngle;// 触摸角度

		// 检测是否超过屏幕的一半
		public boolean isOverHalf() {
			return startPx >= 1248.0f / 2;
		}

		// 检测滑动方向
		public int detectDirec() {
			if (endPy > startPy) {
				direc = EventInfo.TOUCH_DOWN;
			} else if (endPy < startPy) {
				direc = EventInfo.TOUCH_UP;
			}
			return direc;
		}

		// 计算转过的角度
		public int reCountTouchAngle(int mPointX, int mPointY, int mRadius) {
			int touchAngle = 0;
			if (startPy != endPy) {
				double startAngle = Math.atan((startPy - mPointY)
						/ (startPx - mPointX));
				double endAngle = Math.atan((endPy - mPointY)
						/ (endPx - mPointX));
				// 转过的角度
				touchAngle = (int) Math
						.abs(((endAngle - startAngle) / Math.PI * 180));
			}
			return touchAngle;
		}

		// 返回触摸角度
		public int getTouchAngle() {
			return this.touchAngle;
		}

		// 恢复触摸角度
		public void resetTouchAngle() {
			this.touchAngle = 0;
		}

		// 恢复触摸状态
		public void resetTouchStatus() {
			this.touchStatus = EventInfo.ACTION_NO;
		}

		public void setTouchStatus(int touchStatus) {
			this.touchStatus = touchStatus;
		}

		// 自增单击次数
		public void selfAddClickNum() {
			clickNum++;
		}

		// 恢复事件单击信息
		public void resetClickInfo() {
			clickNum = 0;
			firstClickTime = 0l;
			firstClickPx = 0.0;
			firstClickPy = 0.0;
			secondClickTime = 0l;
		}

		public int getTouchStatus() {
			return touchStatus;
		}

		public double getStartPx() {
			return startPx;
		}

		public void setStartPx(double startPx) {
			this.startPx = startPx;
		}

		public double getStartPy() {
			return startPy;
		}

		public void setStartPy(double startPy) {
			this.startPy = startPy;
		}

		public double getEndPx() {
			return endPx;
		}

		public void setEndPx(double endPx) {
			this.endPx = endPx;
		}

		public double getEndPy() {
			return endPy;
		}

		public void setEndPy(double endPy) {
			this.endPy = endPy;
		}

		public int getDirec() {
			return direc;
		}

		public void setDirec(int direc) {
			this.direc = direc;
		}

		public int getClickNum() {
			return clickNum;
		}

		public void setClickNum(int clickNum) {
			this.clickNum = clickNum;
		}

		public Long getFirstClickTime() {
			return firstClickTime;
		}

		public void setFirstClickTime(Long firstClickTime) {
			this.firstClickTime = firstClickTime;
		}

		public Long getSecondClickTime() {
			return secondClickTime;
		}

		public void setSecondClickTime(Long secondClickTime) {
			this.secondClickTime = secondClickTime;
		}

		public double getFirstClickPx() {
			return firstClickPx;
		}

		public void setFirstClickPx(double firstClickPx) {
			this.firstClickPx = firstClickPx;
		}

		public double getFirstClickPy() {
			return firstClickPy;
		}

		public void setFirstClickPy(double firstClickPy) {
			this.firstClickPy = firstClickPy;
		}
	}

	final static class CommonTools {
		// 根据角度返回余弦值
		public static double getCosValueByAngle(int angle) {
			return Math.cos(angle * Math.PI / 180);
		}

		// 根据角度返回正弦值
		public static double getSinValueByAngle(int angle) {
			return Math.sin(angle * Math.PI / 180);
		}
	}

}
